package sniffer

import (
	"encoding/binary"
	"fmt"
)

// UDPPort is a port in a UDP layer.
type UDPPort uint16

// udpFields contains the fields of a udp packet. It is used to describe the
// fields of a packet that needs to be encoded.
type udpFields struct {
	BaseLayer

	// SrcPort is the "source port" field of a udp packet.
	SrcPort UDPPort

	// DstPort is the "destination port" field of a UDP packet.
	DstPort UDPPort

	// Length is the "length" field of a UDP packet.
	Length uint16

	// checksum is the "checksum" field of a UDP packet.
	Checksum uint16

	// 保留原始数据.
	sPort, dPort []byte
}

// 基于udp层解析.
func (udp *udpFields) DecodeFromBytes(dataLayer []byte) error {
	if len(dataLayer) < 8 {
		return fmt.Errorf("Invalid UDP header. Length %d less than 8 ", len(dataLayer))
	}

	udp.SrcPort = UDPPort(binary.BigEndian.Uint16(dataLayer[0:2]))
	udp.sPort = dataLayer[0:2]
	udp.DstPort = UDPPort(binary.BigEndian.Uint16(dataLayer[2:4]))
	udp.dPort = dataLayer[2:4]
	udp.Length = binary.BigEndian.Uint16(dataLayer[4:6])
	udp.Checksum = binary.BigEndian.Uint16(dataLayer[6:8])
	// udp.BaseLayer = BaseLayer{Contents: data[:8]}
	switch {
	case udp.Length >= 8:
		hlen := int(udp.Length)
		if hlen > len(dataLayer) {
			hlen = len(dataLayer)
		}
		udp.Payload = dataLayer[8:hlen]
	case udp.Length == 0: // Jumbogram, use entire rest of data
		udp.Payload = dataLayer[8:]
	default:
		return fmt.Errorf("UDP packet too small: %d bytes", udp.Length)
	}
	return nil
}
